package com.seguriapp.controller;

import java.util.Date;
import java.util.List;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.seguriapp.entities.Complaint;
import com.seguriapp.entities.CrimeCategory;
import com.seguriapp.entities.MediaContent;
import com.seguriapp.entities.MediaContentType;
import com.seguriapp.entities.SeguriAppEntity;
import com.seguriapp.services.ComplaintService;
import com.seguriapp.util.SearchFilterEntity;
import com.seguriapp.util.Util;

/**
 * Represents the controller for the complaint entity
 * 
 * @author Tania Gonzales(taniadgv@gmail.com)
 */
@Controller
@RequestMapping("/complaint")
public class ComplaintController {

  private static final Logger LOGGER = Logger.getLogger(ComplaintController.class);

  @Autowired
  private ComplaintService complaintService;

  private long totalPages;

  @RequestMapping(value = "/save", method = RequestMethod.POST)
  @ResponseBody()
  public String saveComplaint(final @RequestBody String complaintJs) {
    final Long complaintId = complaintService.saveComplaint(getJsonComplaintDataFromString(complaintJs));
    if (complaintId == null) {
      return Util.FALSE;
    } else {
      return complaintId.toString();
    }
  }

  @RequestMapping(value = "/changeComplaintVisibility", method = RequestMethod.POST)
  @ResponseBody()
  public String changeComplaintVisibility(final @RequestBody String complaintJs) {
    return complaintService.changeComplaintVisibility(getJsonComplaintVisibilityDataFromString(complaintJs));
  }

  @RequestMapping(value = "/saveMedia", method = RequestMethod.POST)
  @ResponseBody()
  public String saveComplaintMediaContent(final @RequestBody String complaintMediaContentJs) {
    try {
      getJsonMediaContentDataFromString(complaintMediaContentJs);
    } catch (Exception e) {
      LOGGER.error("Error saving media content", e);
      return Util.FALSE;
    }
    return Util.TRUE;
  }

  @RequestMapping(value = "/list", method = RequestMethod.POST)
  @ResponseBody()
  public String getComplaintsList(final @RequestBody String searchOptionsJs) {
    final List<Complaint> complaintList = getComplaintsData(searchOptionsJs);
    if (complaintList != null) {
      LOGGER.info("Size of complaints list : " + complaintList.size());
      return Util.parseEntityListToJson("complaints", complaintList, totalPages);
    }
    return StringUtils.EMPTY;
  }

  @RequestMapping(value = "/getComplaintMediaContent/{complaintId}", method = RequestMethod.GET)
  @ResponseBody()
  public String getComplaintMediaContentList(@PathVariable("complaintId") Long complaintId) {
    final List<MediaContent> complaintMediaContentList = complaintService.getComplaintMediaContentList(complaintId);
    LOGGER.info("Cantidad de media content de complaint id = " + complaintId + ": " + complaintMediaContentList.size());
    return Util.parseEntityListToJson("mediaContent", complaintMediaContentList);
  }

  @RequestMapping(value = "/mediaContentUploaded/{complaintId}/{fileName}/{fileType}", method = RequestMethod.GET)
  @ResponseBody()
  public String onMediaContentUploaded(@PathVariable("complaintId") Long complaintId, @PathVariable("fileType") String fileType,
      @PathVariable("fileName") String fileName) {
    LOGGER.info("Save Media Content: complaintId = " + complaintId + " fileType = " + fileType + " fileName = " + fileName);
    complaintService.saveMediaContent(complaintId, fileType, fileName);
    return null;
  }

  private void getJsonMediaContentDataFromString(final String complaintMediaContentJs) {
    LOGGER.info("Save media content: " + complaintMediaContentJs);
    if (complaintMediaContentJs == null || complaintMediaContentJs.isEmpty()) {
      return;
    }
    final JSONObject root = JSONObject.fromObject(complaintMediaContentJs);

    if (root.has("complaintId") && root.has("media")) {
      final Complaint complaint = complaintService.findComplaintById(root.getLong("complaintId"));
      final JSONArray mediaListJs = root.getJSONArray("media");
      if (mediaListJs != null) {
        JSONObject jo = null;
        for (int i = 0; i < mediaListJs.size(); i++) {
          jo = mediaListJs.getJSONObject(i);
          final MediaContent mediaContent = new MediaContent();
          mediaContent.setComplaint(complaint);
          mediaContent.setType(MediaContentType.getEnumByString(jo.getString("type")));
          mediaContent.setContent(jo.getString("content"));
          complaintService.saveMediaContent(mediaContent);
        }
      }
    } else {
      LOGGER.info("Complaint media does not have fields: complaintId and media");
    }
  }

  private List<Complaint> getComplaintsData(final String searchOptionsJs) {
    LOGGER.info("Request for complaints: " + searchOptionsJs);
    if (searchOptionsJs == null || searchOptionsJs.isEmpty()) {
      return null;
    }
    final JSONObject root = JSONObject.fromObject(searchOptionsJs);
    if (root.has(Util.PAGE) && root.has("latitude") && root.has("longitude") && root.has(Util.PAGE_SIZE) && root.has(Util.ASCENDING)) {
      final Date startDate = root.has("startDate") ? Util.parseStringToDate(root.getString("startDate")) : null;
      final Date endDate = root.has("endDate") ? Util.parseStringToDate(root.getString("endDate")) : null;
      final String names = root.has("names") ? root.getString("names") : null;
      final String columnSort = root.has(Util.COLUMN_SORT) ? root.getString(Util.COLUMN_SORT) : null;
      final Long userId = root.has("userId") ? root.getLong("userId") : null;

      final SearchFilterEntity searchFilter = new SearchFilterEntity(startDate, endDate, names, root.getDouble("latitude"),
          root.getDouble("longitude"), root.getInt("distance"), root.getLong("policeStationId"), root.getBoolean("searchByPolStation"),
          root.getInt(Util.PAGE), root.getInt(Util.PAGE_SIZE), root.getBoolean(Util.ASCENDING), columnSort, userId);

      totalPages = complaintService.getComplaintsTotalPages(searchFilter);
      return complaintService.listComplaintsOrderByColumn(searchFilter);
    }
    return null;
  }

  private Complaint getJsonComplaintDataFromString(final String complaintJs) {
    LOGGER.info("Save complaint: " + complaintJs);
    if (complaintJs == null || complaintJs.isEmpty()) {
      return null;
    }
    final JSONObject root = JSONObject.fromObject(complaintJs);
    final Complaint complaint = new Complaint();
    if (root.has("names") && root.has("lastNames") && root.has("dni") && root.has("crimeDate") && root.has("entityId")) {
      complaint.setNames(root.getString("names"));
      complaint.setLastNames(root.getString("lastNames"));
      complaint.setAddress(root.getString("address"));
      complaint.setComplaintLatitude(root.getDouble("complaintlatitude"));
      complaint.setComplaintLongitude(root.getDouble("complaintlongitude"));
      complaint.setCrimeLatitude(root.getDouble("crimelatitude"));
      complaint.setCrimeLongitude(root.getDouble("crimelongitude"));
      complaint.setDescription(root.getString("description"));
      complaint.setDni(root.getString("dni"));
      complaint.setEmail(root.getString("email"));
      complaint.setPhone(root.getString("phone"));
      final Date crimeDate = Util.parseStringToDate(root.getString("crimeDate"));
      complaint.setCrimeDate(crimeDate);
      final CrimeCategory crimeCategory = new CrimeCategory();
      crimeCategory.setId(root.getLong("categoryId"));
      complaint.setCategory(crimeCategory);
      final SeguriAppEntity entity = new SeguriAppEntity();
      entity.setId(root.getLong("entityId"));
      complaint.setEntity(entity);
      complaint.setComplaintDate(new Date());
      complaint.setDevideId(root.has("deviceId") ? root.getInt("deviceId") : 0);
    } else {
      LOGGER.info("Complaint does not have fields: names, lastNames, dni, crimeDate, entityId");
      return null;
    }
    if (root.has("id")) {
      complaint.setId(root.getLong("id"));
      if (complaint.getId() == 0) {
        complaint.setId(null);
      }
    }
    return complaint;
  }

  private Complaint getJsonComplaintVisibilityDataFromString(final String complaintJs) {
    LOGGER.info("Save complaint visibility: " + complaintJs);
    if (complaintJs == null || complaintJs.isEmpty()) {
      return null;
    }
    final JSONObject root = JSONObject.fromObject(complaintJs);
    final Complaint complaint = new Complaint();
    if (root.has("complaintId") && root.has("mapVisibility")) {
      complaint.setId(root.getLong("complaintId"));
      complaint.setMapVisivility(root.getBoolean("mapVisibility"));
    } else {
      LOGGER.info("Complaint does not have fields: complaintId, mapVisibility");
      return null;
    }
    return complaint;
  }

}
